From: Konrad Rzeszutek Wilk Date: Wed, 17 Apr 2013 09:35:38 +0000 (+0200) Subject: x86: allow VCPUOP_register_vcpu_info to work again on PVHVM guests X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~6996^2 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=63753b3e;p=xen.git x86: allow VCPUOP_register_vcpu_info to work again on PVHVM guests For details on the hypercall please see commit c58ae69360ccf2495a19bf4ca107e21cf873c75b (VCPUOP_register_vcpu_info) and the c/s 23143 (git commit 6b063a4a6f44245a727aa04ef76408b2e00af9c7) (x86: move pv-only members of struct vcpu to struct pv_vcpu) that introduced the regression. The current code allows the PVHVM guest to make this hypercall. But for PVHVM guest it always returns -EINVAL (-22) for Xen 4.2 and above. Xen 4.1 and earlier worked. The reason is that the check in map_vcpu_info would fail at: if ( v->arch.vcpu_info_mfn != INVALID_MFN ) The reason is that the vcpu_info_mfn for PVHVM guests ends up by defualt with the value of zero (introduced by c/s 23143). The code in vcpu_initialise which initialized vcpu_info_mfn to a valid value (INVALID_MFN), would never be called for PVHVM: if ( is_hvm_domain(d) ) { rc = hvm_vcpu_initialise(v); goto done; } v->arch.pv_vcpu.vcpu_info_mfn = INVALID_MFN; while previously it would be: v->arch.vcpu_info_mfn = INVALID_MFN; [right at the start of the function in Xen 4.1] This fixes the problem with Linux advertising this error: register_vcpu_info failed: err=-22 Signed-off-by: Konrad Rzeszutek Wilk --- diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 6f9cbed7cb..14b6d13d88 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -387,13 +387,14 @@ int vcpu_initialise(struct vcpu *v) vmce_init_vcpu(v); + v->arch.vcpu_info_mfn = INVALID_MFN; + if ( is_hvm_domain(d) ) { rc = hvm_vcpu_initialise(v); goto done; } - v->arch.pv_vcpu.vcpu_info_mfn = INVALID_MFN; spin_lock_init(&v->arch.pv_vcpu.shadow_ldt_lock); @@ -963,14 +964,14 @@ unmap_vcpu_info(struct vcpu *v) { unsigned long mfn; - if ( v->arch.pv_vcpu.vcpu_info_mfn == INVALID_MFN ) + if ( v->arch.vcpu_info_mfn == INVALID_MFN ) return; - mfn = v->arch.pv_vcpu.vcpu_info_mfn; + mfn = v->arch.vcpu_info_mfn; unmap_domain_page_global(v->vcpu_info); v->vcpu_info = &dummy_vcpu_info; - v->arch.pv_vcpu.vcpu_info_mfn = INVALID_MFN; + v->arch.vcpu_info_mfn = INVALID_MFN; put_page_and_type(mfn_to_page(mfn)); } @@ -993,7 +994,7 @@ map_vcpu_info(struct vcpu *v, unsigned long gfn, unsigned offset) if ( offset > (PAGE_SIZE - sizeof(vcpu_info_t)) ) return -EINVAL; - if ( v->arch.pv_vcpu.vcpu_info_mfn != INVALID_MFN ) + if ( v->arch.vcpu_info_mfn != INVALID_MFN ) return -EINVAL; /* Run this command on yourself or on other offline VCPUS. */ @@ -1030,7 +1031,7 @@ map_vcpu_info(struct vcpu *v, unsigned long gfn, unsigned offset) } v->vcpu_info = new_info; - v->arch.pv_vcpu.vcpu_info_mfn = page_to_mfn(page); + v->arch.vcpu_info_mfn = page_to_mfn(page); /* Set new vcpu_info pointer /before/ setting pending flags. */ wmb(); diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 6f9744a58f..bdaf714ef6 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -374,9 +374,6 @@ struct pv_vcpu /* Current LDT details. */ unsigned long shadow_ldt_mapcnt; spinlock_t shadow_ldt_lock; - - /* Guest-specified relocation of vcpu_info. */ - unsigned long vcpu_info_mfn; }; struct arch_vcpu @@ -438,6 +435,9 @@ struct arch_vcpu struct paging_vcpu paging; + /* Guest-specified relocation of vcpu_info. */ + unsigned long vcpu_info_mfn; + uint32_t gdbsx_vcpu_event; /* A secondary copy of the vcpu time info. */